home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’95 / CyberProcDoggie / Source Code / Woof / Woof_Real / RealWoofStream.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-24  |  16.8 KB  |  550 lines  |  [TEXT/MPS ]

  1.  
  2. #include "RealWoofStream.h"
  3.  
  4. #include "MemMgr.h"
  5.  
  6. #include "Debug.h"
  7. #include "MoreMacTCP.h"
  8. #include "WoofURL.h"
  9. #include "BufferManager.h"
  10.  
  11.  
  12.  
  13. #define INHERITED TRealCyberStream
  14.  
  15. #define kMinBuffersAreLow    50            // buffers are no longer low when this percentage is reached
  16. #define kMaxBuffersAreLow    75            // buffers are low when this percentage is reached
  17. #define kMaxReadThreshold    90            // when we have this much of MacTCP's buffer space, stop posting reads
  18.  
  19. TRealWoofStream::TRealWoofStream()
  20. {
  21.     fDoggieTalk = nil;
  22.     fImmediateBuffer = nil;
  23.     fImmediateBufferLength = 0;
  24.     fClientNotifier = nil;
  25.     fOnHold = false;
  26.     fNameText = nil;
  27.     fNameLength = 0;
  28.     fOpen = false;
  29.     fImmediate = false;
  30. }
  31.  
  32.  
  33.  
  34. TRealWoofStream::~TRealWoofStream()
  35. {
  36.     if (fNameText)
  37.     {
  38.         MMFree((Ptr)fNameText);
  39.         ASSERT(!MemError());
  40.         fNameText = nil;
  41.     }
  42.     if (fImmediateBuffer)
  43.     {
  44.         MMFree((Ptr)fImmediateBuffer);
  45.         ASSERT(!MemError());
  46.         fImmediateBuffer = nil;
  47.     }
  48.     
  49.     // delete fBufferManager; ???
  50. }
  51.  
  52.  
  53. void TRealWoofStream::GetSynchronousData(char* buffer, Size* bufferLength)
  54. {
  55.     Boolean foundProcess;
  56.     ProcessSerialNumber process;
  57.     ProcessInfoRec infoRec;
  58.     OSErr result;
  59.     FSSpec processFSSpec;
  60.     Str31 tempStr;
  61.     int i;
  62.     long tempNum;
  63.     
  64.     *bufferLength = 0;
  65.     
  66.     process.highLongOfPSN = 0;
  67.     process.lowLongOfPSN = kNoProcess;
  68.     infoRec.processInfoLength = sizeof(ProcessInfoRec);
  69.     infoRec.processName = (StringPtr) tempStr;
  70.     infoRec.processAppSpec = &processFSSpec;
  71.     
  72.     while ((result = GetNextProcess(&process)) == noErr)
  73.     {
  74.         result = GetProcessInformation(&process, &infoRec);
  75.         if (result != noErr)
  76.             break;
  77.         
  78.         if (EqualString((ConstStr255Param) infoRec.processName, (ConstStr255Param) fNameText, false, true))
  79.             break;
  80.     }
  81.     
  82.     if ((result != noErr) && (result != procNotFound))
  83.         fStreamError = result;
  84.     
  85.     if (result == noErr)
  86.     {
  87.         i = 0;
  88.         
  89.         BlockMove("Process Info for \"", buffer, 24);
  90.         i += 24;
  91.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  92.         i += tempStr[0];
  93.         BlockMove("\"\n", buffer+i, 2);
  94.         i += 2;
  95.         
  96.         BlockMove("\nProcess Serial Number: ", buffer+i, 24);
  97.         i += 24;
  98.         tempNum = (infoRec.processNumber.highLongOfPSN & 0xF0000000) >> 28;
  99.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  100.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x0F000000) >> 24;
  101.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  102.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x00F00000) >> 20;
  103.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  104.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x000F0000) >> 16;
  105.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  106.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x0000F000) >> 12;
  107.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  108.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x00000F00) >> 8;
  109.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  110.         tempNum = (infoRec.processNumber.highLongOfPSN & 0x000000F0) >> 4;
  111.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  112.         tempNum = infoRec.processNumber.highLongOfPSN & 0x0000000F;
  113.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  114.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0xF0000000) >> 28;
  115.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  116.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x0F000000) >> 24;
  117.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  118.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x00F00000) >> 20;
  119.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  120.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x000F0000) >> 16;
  121.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  122.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x0000F000) >> 12;
  123.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  124.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x00000F00) >> 8;
  125.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  126.         tempNum = (infoRec.processNumber.lowLongOfPSN & 0x000000F0) >> 4;
  127.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  128.         tempNum = infoRec.processNumber.lowLongOfPSN & 0x0000000F;
  129.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  130.         
  131.         BlockMove("\nProcess Type:          ", buffer+i, 24);
  132.         i += 24;
  133.         BlockMove(&infoRec.processType, buffer+i, 4);
  134.         i += 4;
  135.         
  136.         BlockMove("\nProcess Creator:       ", buffer+i, 24);
  137.         i += 24;
  138.         BlockMove(&infoRec.processSignature, buffer+i, 4);
  139.         i += 4;
  140.         
  141.         BlockMove("\nProcess Mode:          ", buffer+i, 24);
  142.         i += 24;
  143.         tempNum = (infoRec.processMode & 0xF0000000) >> 28;
  144.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  145.         tempNum = (infoRec.processMode & 0x0F000000) >> 24;
  146.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  147.         tempNum = (infoRec.processMode & 0x00F00000) >> 20;
  148.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  149.         tempNum = (infoRec.processMode & 0x000F0000) >> 16;
  150.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  151.         tempNum = (infoRec.processMode & 0x0000F000) >> 12;
  152.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  153.         tempNum = (infoRec.processMode & 0x00000F00) >> 8;
  154.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  155.         tempNum = (infoRec.processMode & 0x000000F0) >> 4;
  156.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  157.         tempNum = infoRec.processMode & 0x0000000F;
  158.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  159.         
  160.         BlockMove("\nProcess Location:      ", buffer+i, 24);
  161.         i += 24;
  162.         tempNum = (((unsigned long) infoRec.processLocation) & 0xF0000000) >> 28;
  163.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  164.         tempNum = (((unsigned long) infoRec.processLocation) & 0x0F000000) >> 24;
  165.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  166.         tempNum = (((unsigned long) infoRec.processLocation) & 0x00F00000) >> 20;
  167.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  168.         tempNum = (((unsigned long) infoRec.processLocation) & 0x000F0000) >> 16;
  169.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  170.         tempNum = (((unsigned long) infoRec.processLocation) & 0x0000F000) >> 12;
  171.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  172.         tempNum = (((unsigned long) infoRec.processLocation) & 0x00000F00) >> 8;
  173.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  174.         tempNum = (((unsigned long) infoRec.processLocation) & 0x000000F0) >> 4;
  175.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  176.         tempNum = ((unsigned long) infoRec.processLocation) & 0x0000000F;
  177.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  178.         
  179.         BlockMove("\nProcess Size:          ", buffer+i, 24);
  180.         i += 24;
  181.         NumToString(infoRec.processSize, tempStr);
  182.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  183.         i += tempStr[0];
  184.         
  185.         BlockMove("\nProcess Free Mem:      ", buffer+i, 24);
  186.         i += 24;
  187.         NumToString(infoRec.processFreeMem, tempStr);
  188.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  189.         i += tempStr[0];
  190.         
  191.         BlockMove("\nProcess Launched By:   ", buffer+i, 24);
  192.         i += 24;
  193.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0xF0000000) >> 28;
  194.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  195.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x0F000000) >> 24;
  196.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  197.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x00F00000) >> 20;
  198.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  199.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x000F0000) >> 16;
  200.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  201.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x0000F000) >> 12;
  202.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  203.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x00000F00) >> 8;
  204.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  205.         tempNum = (infoRec.processLauncher.highLongOfPSN & 0x000000F0) >> 4;
  206.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  207.         tempNum = infoRec.processLauncher.highLongOfPSN & 0x0000000F;
  208.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  209.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0xF0000000) >> 28;
  210.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  211.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x0F000000) >> 24;
  212.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  213.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x00F00000) >> 20;
  214.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  215.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x000F0000) >> 16;
  216.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  217.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x0000F000) >> 12;
  218.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  219.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x00000F00) >> 8;
  220.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  221.         tempNum = (infoRec.processLauncher.lowLongOfPSN & 0x000000F0) >> 4;
  222.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  223.         tempNum = infoRec.processLauncher.lowLongOfPSN & 0x0000000F;
  224.         *(buffer+(i++)) = (tempNum < 10) ? '0' + tempNum : 'A' + tempNum - 10;
  225.         
  226.         /*
  227.         BlockMove("\nProcess Launch Time:   ", buffer+i, 24);
  228.         i += 24;
  229.         DateString((long) infoRec.processLaunchDate, abbrevDate, (StringPtr) tempStr, nil);
  230.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  231.         i += tempStr[0];
  232.         BlockMove("  ", buffer+i, 2);
  233.         i += 2;
  234.         TimeString((long) infoRec.processLaunchDate, true, (StringPtr) tempStr, nil);
  235.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  236.         i += tempStr[0];
  237.         */
  238.         
  239.         BlockMove("\nProcess Active Time:   ", buffer+i, 24);
  240.         i += 24;
  241.         NumToString(infoRec.processActiveTime, tempStr);
  242.         BlockMove(tempStr+1, buffer+i, tempStr[0]);
  243.         i += tempStr[0];
  244.         BlockMove(" ticks\n", buffer+i, 24);
  245.         
  246.         *bufferLength = i;
  247.     }
  248. }
  249.  
  250.  
  251. void TRealWoofStream::DoggieNotifier(unsigned short eventCode, Ptr buffer, Size bufferSize, OSErr result, void* userDataPtr)
  252. {
  253.     TRealWoofStream* THIS = (TRealWoofStream*) userDataPtr;
  254.     Environment* ev = somGetGlobalEnvironment();
  255.     
  256.     THIS->DoggieProcessEvent(ev, eventCode, buffer, bufferSize, result);
  257. }
  258.  
  259.  
  260. void TRealWoofStream::DoggieProcessEvent(Environment* ev, unsigned short eventCode, Ptr buffer, Size bufferSize, OSErr result)
  261. {
  262.     if (eventCode == kDoggieClosed)
  263.     {
  264.         // The connection was closed.  This means the server has finished sending data.
  265.         fStreamStatus |= kDownloadComplete;
  266.         
  267.         if (fClientNotifier)
  268.             CallCyberStreamNotifyProc(fClientNotifier, kDownloadCompleteEvent, this, fClientUserData);
  269.             
  270.         this->Abort(ev);
  271.     }
  272.     else if (eventCode == kDoggieDoneRead)
  273.     {
  274.         fBufferManager->AddBuffer(buffer, bufferSize);
  275.         
  276.         if (!(fStreamStatus & kDataAvailable))
  277.         {
  278.             fStreamStatus |= kDataAvailable;
  279.             if (fClientNotifier)
  280.                 CallCyberStreamNotifyProc(fClientNotifier, kDataAvailableEvent, this, fClientUserData);
  281.         }
  282.         
  283.         //if (!(fStreamStatus & kBuffersAreLow) && (doggiebuffersarelow))
  284.         if (!(fStreamStatus & kBuffersAreLow) && false)
  285.         {
  286.             fStreamStatus |= kBuffersAreLow;
  287.             if (fClientNotifier)
  288.                 CallCyberStreamNotifyProc(fClientNotifier, kBuffersAreLowEvent, this, fClientUserData);
  289.         }
  290.         
  291.         //if (fBufferManager->OKToAddBuffer() && (doggiebuffersnotrunout)) 
  292.         if (fBufferManager->OKToAddBuffer() && true) 
  293.         {
  294.             // Post another read if the buffer manager can add the buffer and
  295.             // we aren't holding most of protocol's buffer space
  296.             //fDoggieTalk->Read();
  297.         }
  298.         else
  299.         {
  300.             fOnHold = true;
  301.         }
  302.     }
  303.     else if (eventCode == kDoggieError)
  304.     {
  305.         // There was an error, so abort the connection!
  306.         ASSERT(result != noErr);
  307.         fStreamError = result;
  308.         fStreamStatus |= kErrorOccurred;
  309.         fStreamStatus |= kDownloadComplete;
  310.         
  311.         if (fClientNotifier)
  312.             CallCyberStreamNotifyProc(fClientNotifier, kErrorEvent, this, fClientUserData);
  313.         
  314.         this->Abort(ev);
  315.     }
  316. }
  317.  
  318.  
  319. OSErr TRealWoofStream::Initialize(char* url)
  320. {
  321.     OSErr            result = noErr;
  322.     unsigned short    hostNameLen;
  323.     unsigned short    procNameLen;
  324.     char*            hostName;
  325.     char*            procName;
  326.  
  327.     // Initialize fields
  328.  
  329.     fStreamStatus = 0;
  330.     fStreamSize = kStreamSizeUnknown;
  331.     fStreamError = noErr;
  332.  
  333.     // Process URL
  334.     ParseWoofURL(url, &hostName, &hostNameLen, &procName, &procNameLen);
  335.     
  336.     if (!procNameLen)
  337.         return memFullErr;
  338.     
  339.     // get the name
  340.     fNameLength = procNameLen;
  341.     fNameText = (char*) MMAllocate(fNameLength + 1);    // +1 for pascal string length    •Err
  342.     if (!fNameText)
  343.         return memFullErr;
  344.     BlockMove(procName, fNameText + 1, procNameLen);
  345.     fNameText[0] = procNameLen;
  346.     
  347.     if (hostNameLen)
  348.     {
  349.         // Create the connection thingie
  350.         fDoggieTalk = new TDoggieTalkConnection;
  351.         fBufferManager = new TBufferManager;
  352.         if (!fDoggieTalk || !fBufferManager)
  353.             return memFullErr;
  354.         
  355.         result = fBufferManager->Initialize(kArbitraryBufferSize, 
  356.                                             (BufferManagerProcPtr) TRealWoofStream::ContinueReading, 
  357.                                             this);
  358.         if (result != noErr)
  359.             return result;
  360.         
  361.         // %%% get the host address and make an address thing here
  362.     }
  363.     else
  364.     {
  365.         fImmediate = true;
  366.         
  367.         fImmediateBuffer = (char*) MMAllocate(kArbitraryBufferSize);
  368.         if (fImmediateBuffer)
  369.             return memFullErr;
  370.         fImmediateBufferLength = kArbitraryBufferSize;
  371.     }
  372.     
  373.     return result;
  374. }
  375.  
  376.  
  377.  
  378. OSErr TRealWoofStream::OpenWithCallback(Environment* ev, CyberStreamNotifyUPP callback, void* userData)
  379. {
  380.     OSErr err;
  381.     
  382.     fClientNotifier = callback;
  383.     fClientUserData = userData;
  384.     
  385.     err = this->Open(ev);
  386.     
  387.     return err;
  388. }
  389.  
  390.  
  391. OSErr TRealWoofStream::Open(Environment* ev)
  392. {
  393.     if (!fOpen)
  394.     {
  395.         if (fImmediate)
  396.         {
  397.             this->GetSynchronousData(fImmediateBuffer, &fImmediateBufferLength);
  398.             
  399.             if (fStreamError)
  400.             {
  401.                 fStreamStatus |= kErrorOccurred;
  402.                 fStreamStatus |= kDownloadComplete;
  403.                 if (fClientNotifier)
  404.                     CallCyberStreamNotifyProc(fClientNotifier, kErrorEvent, this, fClientUserData);
  405.                 
  406.                 this->Abort(ev);
  407.             }
  408.             else
  409.             {
  410.                 fStreamStatus |= kDataAvailable;
  411.                 if (fClientNotifier)
  412.                     CallCyberStreamNotifyProc(fClientNotifier, kDataAvailableEvent, this, fClientUserData);
  413.             }
  414.         }
  415.         else
  416.         {
  417.             ;//fDoggieTalk->Initialize((CyberDoggiePNotifyProcPtr) TRealWoofStream::DoggieNotifier, this);
  418.         }
  419.         
  420.         fOpen = true;
  421.     }
  422.     return noErr;
  423. }
  424.  
  425.  
  426. void TRealWoofStream::GetBuffer(Environment* ev, Ptr* buffer, Size* bufferSize)
  427. {
  428.     Size    bytesProcessed = 0;
  429.  
  430.     *buffer = nil;
  431.     *bufferSize = 0;
  432.     
  433.     if (fStreamStatus & kDataAvailable)
  434.     {
  435.         if (fImmediate)
  436.         {
  437.             *buffer = (Ptr) fImmediateBuffer;
  438.             *bufferSize = fImmediateBufferLength;
  439.             
  440.             // and end it
  441.             fStreamStatus = kDownloadComplete;
  442.             if (fClientNotifier)
  443.                 CallCyberStreamNotifyProc(fClientNotifier, kDownloadCompleteEvent, this, fClientUserData);
  444.             
  445.             this->Abort(ev);
  446.         }
  447.         else
  448.         {
  449.             ASSERT(!fBufferManager->Empty());
  450.             
  451.             // Process the data and return it to the client
  452.             // Do we need to take out CRLF from bufferSize?
  453.             fBufferManager->RemoveBuffer(buffer, bufferSize);
  454.             
  455.             // if there are no more elements, clear the dataAvailable flag
  456.             if (fBufferManager->Empty())
  457.             {
  458.                 fStreamStatus ^= kDataAvailable;
  459.             }
  460.             
  461.             // if we were on hold because protocol was out of queue elements, 
  462.             // we should try again
  463.             if (fOnHold)
  464.             {
  465.                 fOnHold = false;
  466.                 //fDoggieTalk->Read();
  467.             }
  468.         }
  469.     }
  470. }
  471.  
  472.  
  473.  
  474. void TRealWoofStream::ReleaseBuffer(Environment* /* ev */, Ptr buffer)
  475. {
  476.     //fDoggieTalk->ReleaseBuffer(buffer);
  477.     
  478.     //if ((fStreamStatus & kBuffersAreLow) && (doggiebuffersnotrunout))
  479.     if ((fStreamStatus & kBuffersAreLow) && true)
  480.     {
  481.         // if the user no longer has too many buffers, clear the flag
  482.         fStreamStatus ^= kBuffersAreLow;
  483.         //fDoggieTalk->Read();
  484.     }
  485.     
  486.     // if we were on hold because MacTCP or the buffer manager was out of queue elements, 
  487.     // we should try again if we can
  488.     else if (fOnHold && (fBufferManager->OKToAddBuffer()))
  489.     {
  490.         fOnHold = false;
  491.         //fDoggieTalk->Read();
  492.     }
  493. }
  494.  
  495.  
  496.  
  497. StreamStatus TRealWoofStream::GetStreamStatus(Environment* /* ev */)
  498. {
  499.     return fStreamStatus;
  500. }
  501.  
  502.  
  503.  
  504. short TRealWoofStream::GetTotalDataSize(Environment* /* ev */)
  505. {
  506.     return fStreamSize;
  507. }
  508.  
  509.  
  510.  
  511. OSErr TRealWoofStream::GetStreamError(Environment* /* ev */)
  512. {
  513.     return fStreamError;
  514. }
  515.  
  516.  
  517.  
  518. void TRealWoofStream::Abort(Environment* /* ev */)
  519. {
  520.     // fDoggieTalk->Abort();
  521. }
  522.  
  523.  
  524.  
  525. void TRealWoofStream::GetStatusString(Environment* /* ev */, char* message)
  526. {
  527.     BlockMove("\pNot yet implemented", message, 19);
  528. }
  529.  
  530.  
  531. // Called when the buffer manager thinks it is OK to start reading again
  532. void TRealWoofStream::ContinueReading(void* userData, OSErr result)
  533. {
  534.     TRealWoofStream* THIS = (TRealWoofStream*) userData;
  535.     
  536.     if (result != noErr)
  537.     {
  538.         THIS->fStreamStatus |= kErrorOccurred;
  539.         if (THIS->fClientNotifier)
  540.             CallCyberStreamNotifyProc(THIS->fClientNotifier, kErrorEvent, THIS, THIS->fClientUserData);
  541.     }
  542.     
  543.     else if (THIS->fOnHold)
  544.     {
  545.         THIS->fOnHold = false;
  546.         //THIS->fDoggieTalk-Read();
  547.     }
  548. }
  549.  
  550.